/* w_editor.c
 *
 * Micropolis, Unix Version.  This game was released for the Unix platform
 * in or about 1990 and has been modified for inclusion in the One Laptop
 * Per Child program.  Copyright (C) 1989 - 2007 Electronic Arts Inc.  If
 * you need assistance with this program, you may contact:
 *   http://wiki.laptop.org/go/Micropolis  or email  micropolis@laptop.org.
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.  You should have received a
 * copy of the GNU General Public License along with this program.  If
 * not, see <http://www.gnu.org/licenses/>.
 * 
 *             ADDITIONAL TERMS per GNU GPL Section 7
 * 
 * No trademark or publicity rights are granted.  This license does NOT
 * give you any right, title or interest in the trademark SimCity or any
 * other Electronic Arts trademark.  You may not distribute any
 * modification of this program using the trademark SimCity or claim any
 * affliation or association with Electronic Arts Inc. or its employees.
 * 
 * Any propagation or conveyance of this program must include this
 * copyright notice and these terms.
 * 
 * If you convey this program (or any modifications of it) and assume
 * contractual liability for the program to recipients of it, you agree
 * to indemnify Electronic Arts for any liability that those contractual
 * assumptions impose on Electronic Arts.
 * 
 * You may not misrepresent the origins of this program; modified
 * versions of the program must be marked as such and not identified as
 * the original program.
 * 
 * This disclaimer supplements the one included in the General Public
 * License.  TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
 * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
 * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK.  THE ENTIRE RISK OF
 * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU.  ELECTRONIC ARTS
 * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
 * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
 * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
 * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
 * USAGE, OR TRADE PRACTICE.  ELECTRONIC ARTS DOES NOT WARRANT AGAINST
 * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
 * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
 * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
 * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
 * CORRECTED.  NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
 * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY.  SOME
 * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
 * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
 * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
 * NOT APPLY TO YOU.
 */
#include "sim.h"

Tcl_HashTable EditorCmds;
int DoOverlay = 2;
int BobHeight = 8;

extern Tk_ConfigSpec TileViewConfigSpecs[];

void ClipTheOverlay(SimView * view);
void DrawTheOverlay(SimView * view, GC gc, Pixmap pm, int color,
                    int top, int bottom, int left, int right, int onoverlay);
void DrawOverlay(SimView * view);
void DrawCursor(SimView * view);
void DrawPending(SimView * view);
void DrawOutside(SimView * view);
void HandleAutoGoto(SimView * view);

int EditorCmdconfigure(VIEW_ARGS)
{
    if(argc == 2)
    {
        Tk_ConfigureInfo(interp, view->tkwin, TileViewConfigSpecs, (char *) view, (char *) NULL, 0);
    }
    else if(argc == 3)
    {
        Tk_ConfigureInfo(interp, view->tkwin, TileViewConfigSpecs, (char *) view, argv[2], 0);
    }
    else
    {
        ConfigureTileView(interp, view, argc - 2, argv + 2, TK_CONFIG_ARGV_ONLY);
    }
    return TCL_OK;
}

int EditorCmdposition(VIEW_ARGS)
{
    if((argc != 2) && (argc != 4))
    {
        return TCL_ERROR;
    }
    if(argc == 4)
    {
        if((Tcl_GetInt(interp, argv[2], &view->w_x) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &view->w_y) != TCL_OK))
        {
            return TCL_ERROR;
        }
    }
    sprintf(interp->result, "%d %d", view->w_x, view->w_y);
    return TCL_OK;
}

int EditorCmdsize(VIEW_ARGS)
{
    if((argc != 2) && (argc != 4))
    {
        return TCL_ERROR;
    }
    if(argc == 4)
    {
        int w, h;

        if(Tcl_GetInt(interp, argv[2], &w) != TCL_OK)
        {
            return TCL_ERROR;
        }
        if(Tcl_GetInt(interp, argv[3], &h) != TCL_OK)
        {
            return TCL_ERROR;
        }
        view->w_width = w;
        view->w_height = h;
    }
    sprintf(interp->result, "%d %d", view->w_width, view->w_height);
    return TCL_OK;
}

int EditorCmdAutoGoto(VIEW_ARGS)
{
    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }
    if(argc == 3)
    {
        int val;

        if(Tcl_GetInt(interp, argv[2], &val) != TCL_OK)
        {
            return TCL_ERROR;
        }
        view->auto_goto = val;
        view->auto_going = view->auto_x_goal = view->auto_y_goal = 0;
    }
    sprintf(interp->result, "%d", view->auto_goto);
    return TCL_OK;
}

int EditorCmdSound(VIEW_ARGS)
{
    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }
    if(argc == 3)
    {
        int val;

        if(Tcl_GetInt(interp, argv[2], &val) != TCL_OK)
        {
            return TCL_ERROR;
        }
        view->sound = val;
        view->auto_going = view->auto_x_goal = view->auto_y_goal = 0;
    }
    sprintf(interp->result, "%d", view->sound);
    return TCL_OK;
}

int EditorCmdSkip(VIEW_ARGS)
{
    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }
    if(argc == 3)
    {
        int val;

        if(Tcl_GetInt(interp, argv[2], &val) != TCL_OK)
        {
            return TCL_ERROR;
        }
        view->skip = view->skips = val; // XXX? why setting skips too?
    }
    sprintf(interp->result, "%d", view->skips);
    return TCL_OK;
}

int EditorCmdUpdate(VIEW_ARGS)
{
    if(argc != 2)
    {
        return TCL_ERROR;
    }
    view->skip = 0;
    return TCL_OK;
}

int EditorCmdPan(VIEW_ARGS)
{
    if((argc != 2) && (argc != 4))
    {
        return TCL_ERROR;
    }
    if(argc == 4)
    {
        int x, y;

        if(Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
        {
            return TCL_ERROR;
        }
        if(Tcl_GetInt(interp, argv[3], &y) != TCL_OK)
        {
            return TCL_ERROR;
        }
        DoPanTo(view, x, y);
        Kick();
    }
    sprintf(interp->result, "%d %d", view->pan_x, view->pan_y);
    return TCL_OK;
}

int EditorCmdToolConstrain(VIEW_ARGS)
{
    int x = -1, y = -1, tx, ty;

    if(argc != 4)
    {
        return TCL_ERROR;
    }

    if(Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
    {
        return TCL_ERROR;
    }
    if(Tcl_GetInt(interp, argv[3], &y) != TCL_OK)
    {
        return TCL_ERROR;
    }
    view->tool_x_const = -1;
    view->tool_y_const = -1;
    ViewToTileCoords(view, x, y, &tx, &ty);
    view->tool_x_const = (x == -1) ? -1 : tx;
    view->tool_y_const = (y == -1) ? -1 : ty;
    return TCL_OK;
}

int EditorCmdToolState(VIEW_ARGS)
{
    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }
    if(argc == 3)
    {
        int state;

        if(Tcl_GetInt(interp, argv[2], &state) != TCL_OK)
        {
            return TCL_ERROR;
        }
        setWandState(view, state);
    }
    sprintf(interp->result, "%d", view->tool_state);
    return TCL_OK;
}

int EditorCmdToolMode(VIEW_ARGS)
{
    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }
    if(argc == 3)
    {
        int mode;

        if(Tcl_GetInt(interp, argv[2], &mode) != TCL_OK)
        {
            return TCL_ERROR;
        }
        view->tool_mode = mode;
    }
    sprintf(interp->result, "%d", view->tool_mode);
    return TCL_OK;
}

int EditorCmdDoTool(VIEW_ARGS)
{
    int tool, x, y;

    if(argc != 5)
    {
        return TCL_ERROR;
    }

    if((Tcl_GetInt(interp, argv[2], &tool) != TCL_OK) ||
       (tool < 0) ||
       (tool > lastState) || (Tcl_GetInt(interp, argv[3], &x) != TCL_OK) || (Tcl_GetInt(interp, argv[4], &y) != TCL_OK))
    {
        return TCL_ERROR;
    }

    DoTool(view, tool, x, y);
    Kick();
    return TCL_OK;
}

int EditorCmdToolDown(VIEW_ARGS)
{
    int x, y;

    if(argc != 4)
    {
        return TCL_ERROR;
    }

    if((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK))
    {
        return TCL_ERROR;
    }

    ToolDown(view, x, y);
    Kick();
    return TCL_OK;
}

int EditorCmdToolDrag(VIEW_ARGS)
{
    int x, y;

    if(argc != 4)
    {
        return TCL_ERROR;
    }

    if((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK))
    {
        return TCL_ERROR;
    }

    ToolDrag(view, x, y);
    Kick();
    return TCL_OK;
}

int EditorCmdToolUp(VIEW_ARGS)
{
    int x, y;

    if(argc != 4)
    {
        return TCL_ERROR;
    }

    if((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK))
    {
        return TCL_ERROR;
    }

    ToolUp(view, x, y);
    Kick();
    return TCL_OK;
}

int EditorCmdPanStart(VIEW_ARGS)
{
    int x, y;

    if(argc != 4)
    {
        return TCL_ERROR;
    }

    if((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK))
    {
        return TCL_ERROR;
    }

    view->last_x = x;
    view->last_y = y;
    return TCL_OK;
}

int EditorCmdPanTo(VIEW_ARGS)
{
    int x, y, dx, dy;

    if(argc != 4)
    {
        return TCL_ERROR;
    }

    if((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK))
    {
        return TCL_ERROR;
    }

    dx = (view->tool_x_const == -1) ? (view->last_x - x) : 0;
    dy = (view->tool_y_const == -1) ? (view->last_y - y) : 0;
    if(dx || dy)
    {
        view->last_x = x;
        view->last_y = y;
        DoPanBy(view, dx, dy);
        Kick();
    }
    return TCL_OK;
}

int EditorCmdPanBy(VIEW_ARGS)
{
    int dx, dy;

    if(argc != 4)
    {
        return TCL_ERROR;
    }

    if((Tcl_GetInt(interp, argv[2], &dx) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &dy) != TCL_OK))
    {
        return TCL_ERROR;
    }

    DoPanBy(view, dx, dy);
    Kick();
    return TCL_OK;
}

int EditorCmdTweakCursor(VIEW_ARGS)
{
    XWarpPointer(view->x->dpy, None, None, 0, 0, 0, 0, 0, 0);

    return TCL_OK;
}

int EditorCmdVisible(VIEW_ARGS)
{
    int visible;

    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }

    if(argc == 3)
    {
        if((Tcl_GetInt(interp, argv[2], &visible) != TCL_OK) || (visible < 0) || (visible > 1))
        {
            return TCL_ERROR;
        }

        visible = visible && Tk_IsMapped(view->tkwin);
        view->visible = visible;
    }

    sprintf(interp->result, "%d", view->visible);
    return TCL_OK;
}

int EditorCmdKeyDown(VIEW_ARGS)
{

    if(argc != 3)
    {
        return TCL_ERROR;
    }

    doKeyDown(view, argv[2][0]);
    return TCL_OK;
}

int EditorCmdKeyUp(VIEW_ARGS)
{

    if(argc != 3)
    {
        return TCL_ERROR;
    }

    doKeyUp(view, argv[2][0]);
    return TCL_OK;
}

int EditorCmdTileCoord(VIEW_ARGS)
{
    int x, y;

    if((argc != 2) && (argc != 4))
    {
        return TCL_ERROR;
    }

    if(Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
    {
        return TCL_ERROR;
    }
    if(Tcl_GetInt(interp, argv[3], &y) != TCL_OK)
    {
        return TCL_ERROR;
    }

    ViewToTileCoords(view, x, y, &x, &y);

    sprintf(interp->result, "%d %d", x, y);
    return TCL_OK;
}

int EditorCmdChalkStart(VIEW_ARGS)
{
    int x, y;

    if(argc != 4)
    {
        return TCL_ERROR;
    }

    if((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK))
    {
        return TCL_ERROR;
    }

    ChalkStart(view, x, y, COLOR_WHITE);
    return TCL_OK;
}

int EditorCmdChalkTo(VIEW_ARGS)
{
    int x, y;

    if(argc != 4)
    {
        return TCL_ERROR;
    }

    if((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) || (Tcl_GetInt(interp, argv[3], &y) != TCL_OK))
    {
        return TCL_ERROR;
    }

    ChalkTo(view, x, y);
    return TCL_OK;
}

int EditorCmdAutoGoing(VIEW_ARGS)
{
    int flag;

    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }

    if(argc == 3)
    {
        if((Tcl_GetInt(interp, argv[2], &flag) != TCL_OK))
        {
            return TCL_ERROR;
        }

        view->auto_going = flag;
        if(view->auto_goto == -1)
            view->auto_goto = 0;
    }

    sprintf(interp->result, "%d", view->auto_going);
    return TCL_OK;
}

int EditorCmdAutoSpeed(VIEW_ARGS)
{
    int speed;

    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }

    if(argc == 3)
    {
        if((Tcl_GetInt(interp, argv[2], &speed) != TCL_OK) || (speed < 1))
        {
            return TCL_ERROR;
        }

        view->auto_speed = speed;
    }

    sprintf(interp->result, "%d", view->auto_speed);
    return TCL_OK;
}

int EditorCmdAutoGoal(VIEW_ARGS)
{
    if((argc != 2) && (argc != 4))
    {
        return TCL_ERROR;
    }
    if(argc == 4)
    {
        int x, y, dx, dy;

        if(Tcl_GetInt(interp, argv[2], &x) != TCL_OK)
        {
            return TCL_ERROR;
        }
        if(Tcl_GetInt(interp, argv[3], &y) != TCL_OK)
        {
            return TCL_ERROR;
        }
        view->auto_x_goal = x;
        view->auto_y_goal = y;
        /*
         * actually go there if more than a block away 
         */
        dx = view->pan_x - x;
        dy = view->pan_y - y;
        view->auto_going = (((dx * dx) + (dy * dy)) > (64 * 64));
        if((view->auto_going != 0) && (view->auto_goto == 0))
            view->auto_goto = -1;
    }

    sprintf(interp->result, "%d %d", view->auto_x_goal, view->auto_y_goal);
    return TCL_OK;
}

int EditorCmdSU(VIEW_ARGS)
{
    int su;

    if((argc != 2) && (argc != 4))
    {
        return TCL_ERROR;
    }

    if(argc == 4)
    {
        if((strcmp(argv[3], "xyzzy") != 0) || (Tcl_GetInt(interp, argv[2], &su) != TCL_OK))
        {
            return TCL_ERROR;
        }

        view->super_user = su;
    }

    sprintf(interp->result, "%d", view->super_user);
    return TCL_OK;
}

int EditorCmdShowMe(VIEW_ARGS)
{
    int flag;

    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }

    if(argc == 3)
    {
        if(Tcl_GetInt(interp, argv[2], &flag) != TCL_OK)
        {
            return TCL_ERROR;
        }

        view->show_me = flag;
    }

    sprintf(interp->result, "%d", view->show_me);
    return TCL_OK;
}

int EditorCmdFollow(VIEW_ARGS)
{
    SimSprite *sprite;

    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }

    if(argc == 3)
    {
        view->follow = NULL;
        if(argv[2][0] != '\0')
        {
            for(sprite = sim->sprite; sprite != NULL; sprite = sprite->next)
            {
                if(strcmp(sprite->name, argv[2]) == 0)
                {
                    view->follow = sprite;
                    break;
                }
            }
        }

        if(view->follow != NULL)
        {
            HandleAutoGoto(view);
        }
    }

    sprintf(interp->result, "%s", (view->follow == NULL) ? "" : view->follow->name);
    return TCL_OK;
}

int EditorCmdShowOverlay(VIEW_ARGS)
{
    int flag;

    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }

    if(argc == 3)
    {
        if((Tcl_GetInt(interp, argv[2], &flag) != TCL_OK))
        {
            return TCL_ERROR;
        }

        view->show_overlay = flag;
    }

    sprintf(interp->result, "%d", view->show_overlay);
    return TCL_OK;
}

int EditorCmdOverlayMode(VIEW_ARGS)
{
    int flag;

    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }

    if(argc == 3)
    {
        if((Tcl_GetInt(interp, argv[2], &flag) != TCL_OK))
        {
            return TCL_ERROR;
        }

        view->overlay_mode = flag;
    }

    sprintf(interp->result, "%d", view->overlay_mode);
    return TCL_OK;
}

int EditorCmdDynamicFilter(VIEW_ARGS)
{
    int val;

    if((argc != 2) && (argc != 3))
    {
        return TCL_ERROR;
    }

    if(argc == 3)
    {
        if((Tcl_GetInt(interp, argv[2], &val) != TCL_OK))
        {
            return TCL_ERROR;
        }

        view->dynamic_filter = val;
    }

    sprintf(interp->result, "%d", view->dynamic_filter);
    return TCL_OK;
}

int EditorCmdWriteJpeg(VIEW_ARGS)
{
#if 0
    int val;
    char *fileName = argv[2];
#endif

    if(argc != 3)
    {
        return TCL_ERROR;
    }

    // Write a jpeg file of this view.

    return TCL_OK;
}

void editor_command_init(void)
{
    extern int TileViewCmd(CLIENT_ARGS);

    Tcl_CreateCommand(tk_mainInterp, "editorview", TileViewCmd, (ClientData) MainWindow, (void (*)()) NULL);

    Tcl_InitHashTable(&EditorCmds, TCL_STRING_KEYS);

#define EDITOR_CMD(name) HASHED_CMD(Editor, name)

    EDITOR_CMD(configure);
    EDITOR_CMD(position);
    EDITOR_CMD(size);
    EDITOR_CMD(AutoGoto);
    EDITOR_CMD(Sound);
    EDITOR_CMD(Skip);
    EDITOR_CMD(Update);
    EDITOR_CMD(Pan);
    EDITOR_CMD(ToolConstrain);
    EDITOR_CMD(ToolState);
    EDITOR_CMD(ToolMode);
    EDITOR_CMD(DoTool);
    EDITOR_CMD(ToolDown);
    EDITOR_CMD(ToolDrag);
    EDITOR_CMD(ToolUp);
    EDITOR_CMD(PanStart);
    EDITOR_CMD(PanTo);
    EDITOR_CMD(PanBy);
    EDITOR_CMD(TweakCursor);
    EDITOR_CMD(Visible);
    EDITOR_CMD(KeyDown);
    EDITOR_CMD(KeyUp);
    EDITOR_CMD(TileCoord);
    EDITOR_CMD(ChalkStart);
    EDITOR_CMD(ChalkTo);
    EDITOR_CMD(AutoGoing);
    EDITOR_CMD(AutoSpeed);
    EDITOR_CMD(AutoGoal);
    EDITOR_CMD(SU);
    EDITOR_CMD(ShowMe);
    EDITOR_CMD(Follow);
    EDITOR_CMD(ShowOverlay);
    EDITOR_CMD(OverlayMode);
    EDITOR_CMD(DynamicFilter);
}

int DoEditorCmd(CLIENT_ARGS)
{
    SimView *view = (SimView *) clientData;
    Tcl_HashEntry *ent;
    int result = TCL_OK;
    int (*cmd) ();

    if(argc < 2)
    {
        return TCL_ERROR;
    }

    if((ent = Tcl_FindHashEntry(&EditorCmds, argv[1])))
    {
        cmd = (int (*)()) ent->clientData;
        Tk_Preserve((ClientData) view);
        result = cmd(view, interp, argc, argv);
        Tk_Release((ClientData) view);
    }
    else
    {
        Tcl_AppendResult(interp, "unknown command name: \"", argv[0], " ", argv[1], "\".", (char *) NULL);
        result = TCL_ERROR;
    }
    return result;
}

/*************************************************************************/

void DoNewEditor(SimView * view)
{
    sim->editors++;
    view->next = sim->editor;
    sim->editor = view;
    view->invalid = 1;
}

void DoUpdateEditor(SimView * view)
{
    int dx, dy, i;

    view->updates++;

    if(!view->visible)
    {
        return;
    }

    if((!ShakeNow) &&
//      (!view->invalid) &&
       (!view->update) && (sim_skips || view->skips))
    {
        if(sim_skips)
        {
            if(sim_skip > 0)
            {
                return;
            }
        }
        else
        {
            if(view->skip > 0)
            {
                --view->skip;
                return;
            }
            else
            {
                view->skip = view->skips;
            }
        }
    }

    view->skips = 0;
    view->update = 0;

    HandleAutoGoto(view);

    if(DoAnimation && SimSpeed && !heat_steps && !TilesAnimated)
    {
        TilesAnimated = 1;
        animateTiles();
    }

    if(view->invalid)
    {

        switch (view->type)
        {

            case X_Mem_View:
                MemDrawBeegMapRect(view, view->tile_x, view->tile_y, view->tile_width, view->tile_height);
                break;

            case X_Wire_View:
                WireDrawBeegMapRect(view, view->tile_x, view->tile_y, view->tile_width, view->tile_height);
                break;

        }

        XCopyArea(view->x->dpy, view->pixmap, view->pixmap2, view->x->gc,
                  0, 0, view->screen_width, view->screen_height, view->screen_x, view->screen_y);
        DrawOutside(view);
        if(PendingTool != -1)
        {
            DrawPending(view);
        }
        DrawObjects(view);
        if(view->show_overlay)
        {
            DrawOverlay(view);
        }
    }

    for(dx = dy = i = 0; i < ShakeNow; i++)
    {
        dx += Rand(16) - 8;
        dy += Rand(16) - 8;
    }

    XCopyArea(view->x->dpy, view->pixmap2,
              Tk_WindowId(view->tkwin), view->x->gc, 0, 0, view->w_width, view->w_height, dx, dy);

    DrawCursor(view);

    view->invalid = 0;
}

void HandleAutoGoto(SimView * view)
{
    if(view->follow != NULL)
    {
        int x = view->follow->x + view->follow->x_hot, y = view->follow->y + view->follow->y_hot;

        if((x != view->pan_x) || (y != view->pan_y))
        {
            DoPanTo(view, x, y);
        }
    }
    else if(view->auto_goto && view->auto_going && (view->tool_mode == 0))
    {
        int dx, dy;
        int speed;
        double dist, sloth;

        speed = view->auto_speed;

        if(view->auto_going < 5)
        {
            sloth = ((double) view->auto_going) / 5.0;
        }
        else
        {
            sloth = 1.0;
        }

        dx = view->auto_x_goal - view->pan_x;
        dy = view->auto_y_goal - view->pan_y;

        dist = sqrt((double) ((dx * dx) + (dy * dy)));

        if(dist < (speed * sloth))
        {
            view->auto_going = 0;
            if(view->auto_goto == -1)
                view->auto_goto = 0;
            DoPanTo(view, view->auto_x_goal, view->auto_y_goal);
            NewMap = 1;
            DidStopPan(view);
        }
        else
        {
            double atan2(), cos(), sin();
            double direction, vx, vy;
            double co, si;

            direction = (double) atan2((double) dy, (double) dx);
            co = (double) cos(direction);
            si = (double) sin(direction);
            vx = co * (double) speed;
            vy = si * (double) speed;

            vx *= sloth;
            vy *= sloth;
            speed *= sloth;

            vx += 0.5;
            vy += 0.5;

            DoPanBy(view, (int) (vx), (int) (vy));
            view->auto_going++;
        }
    }
}

void DrawOutside(SimView * view)
{
    Pixmap pm = view->pixmap2;
    int left = (view->w_width / 2) - view->pan_x;
    int right = left + view->i_width;
    int top = (view->w_height / 2) - view->pan_y;
    int bottom = top + view->i_height;

    if((top > 0) || (bottom < view->w_height) || (left > 0) || (right < view->w_width))
    {
        if(view->x->color)
        {
            XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_BLACK]);
        }
        else
        {
            XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_WHITE]);
        }

        if(top > 0)
            XFillRectangle(view->x->dpy, pm, view->x->gc, 0, 0, view->w_width, top);
        if(bottom < view->w_height)
            XFillRectangle(view->x->dpy, pm, view->x->gc, 0, bottom, view->w_width, view->w_height - bottom);
        if(left > 0)
            XFillRectangle(view->x->dpy, pm, view->x->gc, 0, top, left, bottom - top);
        if(right < view->w_width)
            XFillRectangle(view->x->dpy, pm, view->x->gc, right, top, view->w_width - right, bottom - top);
    }
}

char CursorDashes[] = { 4, 4 };

void DrawPending(SimView * view)
{
    Pixmap pm = view->pixmap2;
    int left = (view->w_width / 2) - view->pan_x;
    int top = (view->w_height / 2) - view->pan_y;
    int x, y, size;
    char *iconname = NULL;

    x = (PendingX - toolOffset[PendingTool]) << 4;
    y = (PendingY - toolOffset[PendingTool]) << 4;
    size = toolSize[PendingTool] << 4;
    x += left;
    y += top;

    XSetStipple(view->x->dpy, view->x->gc, view->x->gray50_stipple);
    XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
    XSetForeground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_BLACK]);
    XSetFillStyle(view->x->dpy, view->x->gc, FillStippled);
    XFillRectangle(view->x->dpy, pm, view->x->gc, x, y, size, size);
    XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);

    switch (PendingTool)
    {
        case residentialState:
            iconname = "@images/res.xpm";
            break;
        case commercialState:
            iconname = "@images/com.xpm";
            break;
        case industrialState:
            iconname = "@images/ind.xpm";
            break;
        case fireState:
            iconname = "@images/fire.xpm";
            break;
        case policeState:
            iconname = "@images/police.xpm";
            break;
        case stadiumState:
            iconname = "@images/stadium.xpm";
            break;
        case seaportState:
            iconname = "@images/seaport.xpm";
            break;
        case powerState:
            iconname = "@images/coal.xpm";
            break;
        case nuclearState:
            iconname = "@images/nuclear.xpm";
            break;
        case airportState:
            iconname = "@images/airport.xpm";
            break;
        default:
            break;
    }

    if(iconname != NULL)
    {
        Pixmap icon = Tk_GetPixmap(view->interp, view->tkwin, iconname);
        float f;
        int i;

        gettimeofday(&now_time, NULL);
        f = (2 * now_time.tv_usec / 1000000.0);
        if(f > 1.0)
            f = 2.0 - f;
        i = (int) (f * BobHeight * (Players - Votes));

        if(icon != None)
        {
            XCopyArea(view->x->dpy, icon, pm, view->x->gc, 0, 0, size, size, x + i, y - i);
        }
    }
}

void DrawCursor(SimView * view)
{
    Pixmap pm = Tk_WindowId(view->tkwin);
    int left = (view->w_width / 2) - view->pan_x;
    int top = (view->w_height / 2) - view->pan_y;
    int x, y, mode, size, offset, fg, bg, light, dark;
    SimView *v;

    for(v = sim->editor; v != NULL; v = v->next)
    {
        mode = v->tool_mode;
        if((v->show_me != 0) && ((mode == -1) || v->tool_showing))
        {
            x = v->tool_x;
            y = v->tool_y;
            if(mode == -1)
            {                   /* pan cursor */

                x += left;
                y += top;

                XSetLineAttributes(view->x->dpy, view->x->gc, 3, LineSolid, CapRound, JoinMiter);
                XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_BLACK]);
                XDrawLine(view->x->dpy, pm, view->x->gc, x - 6, y - 6, x + 6, y + 6);
                XDrawLine(view->x->dpy, pm, view->x->gc, x - 6, y + 6, x + 6, y - 6);
                XDrawLine(view->x->dpy, pm, view->x->gc, x - 8, y, x + 8, y);
                XDrawLine(view->x->dpy, pm, view->x->gc, x, y + 8, x, y - 8);
                XSetLineAttributes(view->x->dpy, view->x->gc, 1, LineSolid, CapRound, JoinMiter);
                XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_WHITE]);
                XDrawLine(view->x->dpy, pm, view->x->gc, x - 6, y - 6, x + 6, y + 6);
                XDrawLine(view->x->dpy, pm, view->x->gc, x - 6, y + 6, x + 6, y - 6);
                XDrawLine(view->x->dpy, pm, view->x->gc, x - 8, y, x + 8, y);
                XDrawLine(view->x->dpy, pm, view->x->gc, x, y + 8, x, y - 8);
                XSetLineAttributes(view->x->dpy, view->x->gc, 1, LineSolid, CapButt, JoinMiter);

            }
            else
            {                   /* edit cursor */

                size = toolSize[v->tool_state];
                fg = toolColors[v->tool_state] & 0xff;
                light = COLOR_WHITE;
                dark = COLOR_BLACK;
                if(mode == 1)
                {
                    int temp = dark;

                    dark = light;
                    light = temp;
                }
                switch (v->tool_state)
                {

                    case chalkState:
                        x += left;
                        y += top;
                        if(mode == 1)
                        {
                            offset = 2;
                        }
                        else
                        {
                            offset = 0;

                            if(view->x->color)
                            {
                                XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_MEDIUMGRAY]);
                                XFillArc(view->x->dpy, pm, view->x->gc, x - 8, y + 7, 7, 7, 0, 360 * 64);
                            }
                            else
                            {
                                XSetStipple(view->x->dpy, view->x->gc, view->x->gray50_stipple);
                                XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
                                XSetForeground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_BLACK]);
                                XSetBackground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_WHITE]);
                                XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
                                XFillArc(view->x->dpy, pm, view->x->gc, x - 8, y + 7, 7, 7, 0, 360 * 64);
                                XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
                            }
                        }

                        if(view->x->color)
                        {
                            XSetLineAttributes(view->x->dpy, view->x->gc, 3, LineSolid, CapRound, JoinMiter);
                            XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_LIGHTGRAY]);
                            XFillArc(view->x->dpy, pm, view->x->gc, x - 6 - offset, y + 5 + offset, 7, 7, 0, 360 * 64);
                            XDrawLine(view->x->dpy, pm, view->x->gc,
                                      x + 13 - offset, y - 5 + offset, x - 1 - offset, y + 9 + offset);
                            XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_WHITE]);
                            XDrawLine(view->x->dpy, pm, view->x->gc,
                                      x + 11 - offset, y - 7 + offset, x - 3 - offset, y + 7 + offset);
                            XFillArc(view->x->dpy, pm, view->x->gc, x + 8 - offset, y - 9 + offset, 7, 7, 0, 360 * 64);
                            XSetLineAttributes(view->x->dpy, view->x->gc, 1, LineSolid, CapButt, JoinMiter);
                        }
                        else
                        {
                            XSetLineAttributes(view->x->dpy, view->x->gc, 3, LineSolid, CapRound, JoinMiter);
                            XSetStipple(view->x->dpy, view->x->gc, view->x->gray25_stipple);
                            XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
                            XSetForeground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_BLACK]);
                            XSetBackground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_WHITE]);
                            XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
                            XFillArc(view->x->dpy, pm, view->x->gc, x - 6 - offset, y + 5 + offset, 7, 7, 0, 360 * 64);
                            XDrawLine(view->x->dpy, pm, view->x->gc,
                                      x + 13 - offset, y - 5 + offset, x - 1 - offset, y + 9 + offset);
                            XSetStipple(view->x->dpy, view->x->gc, view->x->gray75_stipple);
                            XDrawLine(view->x->dpy, pm, view->x->gc,
                                      x + 11 - offset, y - 7 + offset, x - 3 - offset, y + 7 + offset);
                            XFillArc(view->x->dpy, pm, view->x->gc, x + 8 - offset, y - 9 + offset, 7, 7, 0, 360 * 64);
                            XSetLineAttributes(view->x->dpy, view->x->gc, 1, LineSolid, CapButt, JoinMiter);
                            XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
                        }

                        break;

                    case eraserState:
                        x += left;
                        y += top;
                        if(mode == 1)
                        {
                            offset = 0;
                        }
                        else
                        {
                            offset = 2;

                            if(view->x->color)
                            {
                                XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_MEDIUMGRAY]);
                                XFillRectangle(view->x->dpy, pm, view->x->gc, x - 8, y - 8, 16, 16);
                            }
                            else
                            {
                                XSetStipple(view->x->dpy, view->x->gc, view->x->gray50_stipple);
                                XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
                                XSetForeground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_BLACK]);
                                XSetBackground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_WHITE]);
                                XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
                                XFillRectangle(view->x->dpy, pm, view->x->gc, x - 8, y - 8, 16, 16);
                                XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
                            }
                        }

                        if(view->x->color)
                        {
                            XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_LIGHTGRAY]);
                        }
                        else
                        {
                            XSetStipple(view->x->dpy, view->x->gc, view->x->gray75_stipple);
                            XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
                            XSetForeground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_BLACK]);
                            XSetBackground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_WHITE]);
                            XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
                        }

                        /*
                         * top 
                         */
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x - 8 + offset, y - 8 - offset, x + 8 + offset, y - 8 - offset);
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x - 7 + offset, y - 7 - offset, x + 7 + offset, y - 7 - offset);
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x - 6 + offset, y - 6 - offset, x + 6 + offset, y - 6 - offset);

                        /*
                         * left 
                         */
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x - 8 + offset, y - 8 - offset, x - 8 + offset, y + 8 - offset);
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x - 7 + offset, y - 7 - offset, x - 7 + offset, y + 7 - offset);
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x - 6 + offset, y - 6 - offset, x - 6 + offset, y + 6 - offset);

                        if(view->x->color)
                        {
                            XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_BLACK]);
                        }
                        else
                        {
                            XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
                        }

                        /*
                         * bottom 
                         */
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x - 7 + offset, y + 7 - offset, x + 8 + offset, y + 7 - offset);
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x - 6 + offset, y + 6 - offset, x + 7 + offset, y + 6 - offset);
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x - 5 + offset, y + 5 - offset, x + 6 + offset, y + 5 - offset);

                        /*
                         * right 
                         */
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x + 7 + offset, y + 8 - offset, x + 7 + offset, y - 7 - offset);
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x + 6 + offset, y + 7 - offset, x + 6 + offset, y - 6 - offset);
                        XDrawLine(view->x->dpy, pm, view->x->gc,
                                  x + 5 + offset, y + 6 - offset, x + 5 + offset, y - 5 - offset);

                        if(view->x->color)
                        {
                            XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_DARKGRAY]);
                            XFillRectangle(view->x->dpy, pm, view->x->gc, x - 5 + offset, y - 5 - offset, 10, 10);
                        }
                        else
                        {
                            XSetStipple(view->x->dpy, view->x->gc, view->x->gray50_stipple);
                            XSetForeground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_BLACK]);
                            XSetBackground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_WHITE]);
                            XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
                            XFillRectangle(view->x->dpy, pm, view->x->gc, x - 5 + offset, y - 5 - offset, 10, 10);
                            XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
                        }

                        break;

                    default:
                        offset = toolOffset[v->tool_state];

                        bg = (toolColors[v->tool_state] >> 8) & 0xff;

                        x = (x & ~15) - (offset << 4);
                        y = (y & ~15) - (offset << 4);
                        size <<= 4;
                        x += left;
                        y += top;

                        XSetForeground(view->x->dpy, view->x->gc, view->pixels[dark]);
                        XDrawRectangle(view->x->dpy, pm, view->x->gc, x - 1, y - 1, size + 4, size + 4);
                        XDrawLine(view->x->dpy, pm, view->x->gc, x - 3, y + size + 3, x - 1, y + size + 3);
                        XDrawLine(view->x->dpy, pm, view->x->gc, x + size + 3, y - 3, x + size + 3, y - 1);

                        XSetForeground(view->x->dpy, view->x->gc, view->pixels[light]);
                        XDrawRectangle(view->x->dpy, pm, view->x->gc, x - 4, y - 4, size + 4, size + 4);
                        XDrawLine(view->x->dpy, pm, view->x->gc, x - 4, y + size + 1, x - 4, y + size + 3);
                        XDrawLine(view->x->dpy, pm, view->x->gc, x + size + 1, y - 4, x + size + 3, y - 4);

                        if(view->x->color)
                        {
                            if(fg == bg)
                            {
                                XSetForeground(view->x->dpy, view->x->gc, view->x->pixels[fg]);
                                XSetLineAttributes(view->x->dpy, view->x->gc, 2, LineSolid, CapButt, JoinMiter);
                            }
                            else
                            {
                                XSetForeground(view->x->dpy, view->x->gc, view->x->pixels[fg]);
                                XSetBackground(view->x->dpy, view->x->gc, view->pixels[bg]);

                                XSetLineAttributes(view->x->dpy, view->x->gc, 2, LineDoubleDash, CapButt, JoinMiter);
                                XSetDashes(view->x->dpy, view->x->gc, 0, CursorDashes, 2);
                            }
                        }
                        else
                        {
                            XSetStipple(view->x->dpy, view->x->gc, view->x->gray50_stipple);
                            XSetForeground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_BLACK]);
                            XSetBackground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_WHITE]);
                            XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
                            XSetLineAttributes(view->x->dpy, view->x->gc, 2, LineSolid, CapButt, JoinMiter);
                        }

                        XDrawLine(view->x->dpy, pm, view->x->gc, x - 2, y - 1, x - 2, y + size + 3);
                        XDrawLine(view->x->dpy, pm, view->x->gc, x - 1, y + size + 2, x + size + 3, y + size + 2);
                        XDrawLine(view->x->dpy, pm, view->x->gc, x + size + 2, y + size + 1, x + size + 2, y - 3);
                        XDrawLine(view->x->dpy, pm, view->x->gc, x + size + 1, y - 2, x - 3, y - 2);

                        if(!view->x->color)
                        {
                            XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
                        }
                        XSetLineAttributes(view->x->dpy, view->x->gc, 1, LineSolid, CapButt, JoinMiter);

                        break;
                }
            }
        }
    }
}

void TimeElapsed(struct timeval *elapsed, struct timeval *start, struct timeval *finish)
{
    int usec = finish->tv_usec - start->tv_usec;
    int sec = finish->tv_sec - start->tv_sec;

    while(usec < 0)
    {
        usec += 1000000;
        sec--;
    }
    elapsed->tv_usec = usec;
    elapsed->tv_sec = sec;
}

void DrawOverlay(SimView * view)
{
    int width = view->w_width;
    int height = view->w_height;
    int left = view->pan_x - (width / 2);
    int top = view->pan_y - (height / 2);
    int right = left + width;
    int bottom = top + height;
    int showing = 0;
    Ink *ink;
    struct timeval start, finished, elapsed;

    for(ink = sim->overlay; ink != NULL; ink = ink->next)
    {
        if((ink->bottom >= top) && (ink->top <= bottom) && (ink->right >= left) && (ink->left <= right))
        {
            showing = 1;
            break;
        }
    }

    if(!showing)
        return;

/* overlay_mode state machine:
   0 => overlay invalid: 
        draw lines to pm => 1
   1 => overlay stable: 
        sync, time draw lines to pm => 2
   2 => overlay stable: 
        draw lines to ol,
        sync, time clip ol to pm,
        lines faster? => 3,
	clipping faster? => 4
   3 => lines faster: 
        draw lines to pm => 3
   4 => clipping faster: 
        clip ol to pm => 4
*/

    switch (view->overlay_mode)
    {
        case 0:
            DrawTheOverlay(view, view->x->gc, view->pixmap2, view->pixels[COLOR_WHITE], top, bottom, left, right, 0);
            view->overlay_mode = 1;
            break;
        case 1:
            XSync(view->x->dpy, False);
            gettimeofday(&start, NULL);
            DrawTheOverlay(view, view->x->gc, view->pixmap2, view->pixels[COLOR_WHITE], top, bottom, left, right, 0);
            XSync(view->x->dpy, False);
            gettimeofday(&finished, NULL);
            TimeElapsed(&view->overlay_time, &start, &finished);
            view->overlay_mode = 2;
            break;
        case 2:
            XSetForeground(view->x->dpy, view->x->overlay_gc, 0);
            XFillRectangle(view->x->dpy, view->overlay_pixmap, view->x->overlay_gc,
                           0, 0, view->m_width, view->m_height);
            DrawTheOverlay(view, view->x->overlay_gc, view->overlay_pixmap, 1, top, bottom, left, right, 1);
            XSync(view->x->dpy, False);
            gettimeofday(&start, NULL);
            ClipTheOverlay(view);
            XSync(view->x->dpy, False);
            gettimeofday(&finished, NULL);
            TimeElapsed(&elapsed, &start, &finished);
            if((elapsed.tv_sec > view->overlay_time.tv_sec) ||
               ((elapsed.tv_sec == view->overlay_time.tv_sec) && ((elapsed.tv_usec > view->overlay_time.tv_usec))))
            {
                view->overlay_mode = 3;
            }
            else
            {
                view->overlay_mode = 4;
            }
            break;
        case 3:
            DrawTheOverlay(view, view->x->gc, view->pixmap2, view->pixels[COLOR_WHITE], top, bottom, left, right, 0);
            break;
        case 4:
            ClipTheOverlay(view);
            break;
    }
}

void
DrawTheOverlay(SimView * view, GC gc, Pixmap pm, int color, int top, int bottom, int left, int right, int onoverlay)
{
    Ink *ink;

    if(view->x->color)
    {
        XSetForeground(view->x->dpy, gc, color);
        XSetLineAttributes(view->x->dpy, gc, 3, LineSolid, CapButt, JoinBevel);
    }
    else
    {
        if(!onoverlay)
        {
            XSetStipple(view->x->dpy, gc, view->x->gray50_stipple);
            XSetTSOrigin(view->x->dpy, gc, view->updates & 1, 0);
            XSetBackground(view->x->dpy, gc, 0);
            XSetFillStyle(view->x->dpy, gc, FillOpaqueStippled);
        }
        XSetForeground(view->x->dpy, gc, 1);
        XSetLineAttributes(view->x->dpy, gc, 3, LineSolid, CapButt, JoinBevel);
    }
    for(ink = sim->overlay; ink != NULL; ink = ink->next)
    {
        if((ink->bottom >= top) && (ink->top <= bottom) && (ink->right >= left) && (ink->left <= right))
        {
            if(ink->length <= 1)
            {
                XFillArc(view->x->dpy, pm, gc, ink->x - 3, ink->y - 3, 6, 6, 0, 360 * 64);
            }
            else
            {
                ink->points[0].x = ink->x - left;
                ink->points[0].y = ink->y - top;
                XDrawLines(view->x->dpy, pm, gc, ink->points, ink->length, CoordModePrevious);
            }
        }
    }
    if(!view->x->color)
    {
        XSetFillStyle(view->x->dpy, gc, FillSolid);
    }
    XSetLineAttributes(view->x->dpy, gc, 1, LineSolid, CapButt, JoinMiter);
}

void ClipTheOverlay(SimView * view)
{
    if(view->x->color)
    {
        XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_WHITE]);
        XSetFillStyle(view->x->dpy, view->x->gc, FillStippled);
        XSetStipple(view->x->dpy, view->x->gc, view->overlay_pixmap);
        XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
        XFillRectangle(view->x->dpy, view->pixmap2, view->x->gc, 0, 0, view->w_width, view->w_height);
        XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
    }
    else
    {
        XSetStipple(view->x->dpy, view->x->gc, view->x->gray50_stipple);
        XSetTSOrigin(view->x->dpy, view->x->gc, view->updates & 1, 0);
        XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_WHITE]);
        XSetBackground(view->x->dpy, view->x->gc, view->pixels[COLOR_BLACK]);
        XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
        XSetLineAttributes(view->x->dpy, view->x->gc, 3, LineSolid, CapButt, JoinBevel);
        XSetClipOrigin(view->x->dpy, view->x->gc, 0, 0);
        XSetClipMask(view->x->dpy, view->x->gc, view->overlay_pixmap);
        XFillRectangle(view->x->dpy, view->pixmap2, view->x->gc, 0, 0, view->w_width, view->w_height);
        XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
        XSetClipMask(view->x->dpy, view->x->gc, None);
    }
}
